﻿#region BSD license

/*
 * Copyright (c) 2008, Thomas "zeroflag" Kraemer. All rights reserved.
 * Copyright (c) 2008, Anders "anonimasu" Helin. All rights reserved.
 * Copyright (c) 2008, The zeroflag.Components.NET Team. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 * Neither the name of the zeroflag.Components.NET Team nor the names of its contributors may 
 * be used to endorse or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#endregion BSD license

#region SVN Version Information

///	<file>
///		<!-- Last modification of this file: -->
///		<revision>$Rev: 60 $</revision>
///		<author>$Author: zeroflag $</author>
///		<id>$Id: Module.cs 60 2008-12-05 20:21:08Z zeroflag $</id>
///	</file>

#endregion SVN Version Information

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace zeroflag.Components
{
	public abstract class Module<CoreT> : Module, IComponent<CoreT>
		where CoreT : Core<CoreT>
	{
		#region Properties

		#region Core

		private CoreT _Core;

		/// <summary>
		/// The core this module belongs to.
		/// </summary>
		[SerializerIgnore]
		public CoreT Core
		{
			get { return _Core ?? this as CoreT ?? (this.Outer != null ? this.Outer.CoreBase as CoreT : null); }
			set
			{
				if (_Core != value)
				{
					this.OnCoreChanged(_Core, _Core = value);
				}
			}
		}

		#region CoreChanged event

		private event Component<CoreT>.CoreChangedHandler _CoreChanged;

		/// <summary>
		/// Occurs when Core changes.
		/// </summary>
		public event Component<CoreT>.CoreChangedHandler CoreChanged
		{
			add { this._CoreChanged += value; }
			remove { this._CoreChanged -= value; }
		}

		/// <summary>
		/// Raises the CoreChanged event.
		/// </summary>
		protected virtual void OnCoreChanged(CoreT oldvalue, CoreT newvalue)
		{
			if (newvalue != null)
			{
				if (this.HasInner)
				{
					foreach (var comp in this.Inner)
					{
						comp.CoreBase = newvalue;
					}
				}
				if (this.Outer != null && this.Outer.CoreBase == null)
				{
					this.Outer.CoreBase = newvalue;
				}
			}
			// if there are event subscribers...
			if (this._CoreChanged != null)
			{
				// call them...
				this._CoreChanged(this, oldvalue, newvalue);
			}
		}

		#endregion CoreChanged event

		#endregion Core

		#endregion

		#region IComparable<Module> Members

		/// <summary>
		/// Compare two modules for order.
		/// This represents the execution order and can be used for dependency handling.
		/// e.g. the rendering module (should run last) will return 1 (greater than) for any other module.
		/// </summary>
		/// <param name="other"></param>
		/// <returns>
		/// Less than zero 
		///  This Module is less than the other Module. This module has a lower priority.
		/// Zero 
		///  This Module is equal to other. Equal priority.
		/// Greater than zero 
		///  This Module is greater than Module. Higher priority, executed first.
		/// </returns>
		public virtual int CompareTo(Module other)
		{
			return 0;
		}

		#endregion

		public override void Update()
		{
			try
			{
				base.Update();
			}
			catch (Exception exc)
			{
				this.Log.Error(exc);
			}
		}
	}
}